/** \file GameController.hpp
 *  \author Adrian Schweizer
 *  \created  $So 30 Sep 04:40:47 pm CEST 2007 schwadri@SchwadriLaptop$
 *  \modified $So 20 Jan 03:24:12 pm CET 2008 schwadri@SchwadriLaptop.local$
 */

#ifndef _game_GameController_hpp_
#define _game_GameController_hpp_

#include "../network/Types.hpp"
#include "../network/Client.hpp"
#include "TeamManager.hpp"

#include "GameOptions.hpp"
#include <string>
//#include "ActionDispatcher.hpp"

//TODO: move to network/Types.hpp
namespace network {
    //fwd decl
    class NetworkController;
}

namespace game {

    /** \brief Manages the Game Logic
     *
     *  May run in Lobby-Mode or Game-Mode
     */
    class GameController    :   public boost::signals::trackable
    {
    public:
        static const int LIMIT_CLIENT_NAME_SIZE = 20;   ///<Maximum length of a client name
        GameController();
        ~GameController();

        /** \brief The Mode in which the Controller is running*/
        enum RunMode {
            LOBBY,      ///<Lobby Mode
            GAME,       ///<The Game is running
            CONNECTING, ///<Connecting to a Game
            CONNECTED,
            DONE        ///<Game has finished. Show Victory Screen
        };

        network::NetworkController& Network()   { return *m_network; }  ///<Returns a Reference to the NetworkController

        /** \brief Hosts a new game*/
        void HostGame(const network::Address& addr, const std::string& server_name);

        /** \brief Join a game*/
        void JoinGame(const network::Address& addr);
        
        TeamManager&    Teams()     { return m_teams; }

    private:
        /**\name NetworkController Signal Handlers*///@{

        //notifications about other clients
        void OnClientDisconnected(network::Client::Id cid, network::DisconnectReason reason);
        void OnClientConnected(network::Client::Id cid);

        //regarding our connection
        void OnConnected(network::Client::Id cid);
        void OnDisconnected(network::DisconnectReason reason);
        //@}


        class Impl;
        void RunGame();
        void RunLobby();
        network::Client::Id         m_my_cid;   ///<My Client::Id
        Impl*                       m_impl;
        bool                        m_run;      ///<True if the internal loop should continue running
        RunMode                     m_mode;     ///<The mode we're currently in \sa RunMode
        TeamManager                 m_teams;    ///<T
        network::NetworkController* m_network;  ///<Network Handling
        //action::Dispatcher          m_dispatch;
        GameOptions                 m_options;
    };

} // namespace game

#endif //  _game_GameController_hpp_
